﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DiscoveryLogic.Analytics.DataObjects;
using DiscoveryLogic.Analytics.DataObjects.Filters;
using DiscoveryLogic.Common.Utilities;

namespace DiscoveryLogic.Analytics.Modules.Filters
{
    /// <summary>
    /// Interaction logic for NetworkEntityExcludeSetting.xaml
    /// </summary>
    public partial class NetworkEntityExcludeSetting : UserControl
    {
        public delegate void OnNetworkExclustionSettingUpdated(NetworkExclusionSetting exSetting);
        public event OnNetworkExclustionSettingUpdated NetworkExclustionSettingUpdated;

        private NetworkExclusionSetting netExSetting;

        public NetworkEntityExcludeSetting(string networkName)
        {
            InitializeComponent();
            netExSetting = NetworkExclusionSetting.Read(networkName);
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.cboEntityType1.Items.Clear();
            foreach(EntityType entityType in Enum.GetValues(typeof(EntityType)))
            {
                this.cboEntityType1.Items.Add(entityType.ToString());
            }
            this.cboOps1.Items.Clear();
            foreach(SqlOp op in Enum.GetValues(typeof(SqlOp)))
            {
                this.cboOps1.Items.Add(SqlOpHelper.ToString(op));
            }
        }

        private void cboEntityType1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if(this.cboEntityType1.SelectedIndex>=0)
            {
                EntityType entityType =
                    (EntityType) Enum.Parse(typeof (EntityType), this.cboEntityType1.SelectedItem.ToString());
                this.cboFieldName1.Items.Clear();
                PropertyInfo[] props = EntityTypeUtil.GetProperties(entityType);
                
                foreach(PropertyInfo prop in props)
                {
                    if(prop.CanRead && prop.CanWrite)
                    {
                        this.cboFieldName1.Items.Add(prop.Name);
                    }
                }
            }
        }

        private void btnAddCondition_Click(object sender, RoutedEventArgs e)
        {
            if(this.cboFieldName1.SelectedIndex>=0 && this.cboOps1.SelectedIndex>=0 && 
                !string.IsNullOrEmpty(this.txtCondition1.Text))
            {
                string query =
                    string.Format("{0}.{1}{2}{3}",
                                  this.cboEntityType1.SelectedItem.ToString(),
                                  this.cboFieldName1.SelectedItem.ToString(),
                                  this.cboOps1.SelectedItem.ToString(),
                                  this.txtCondition1.Text);
                this.lbQueries.Items.Add(query);
            }
        }

        private void btnRemoveCondition_Click(object sender, RoutedEventArgs e)
        {
            if(this.lbQueries.SelectedItem !=null)
                this.lbQueries.Items.Remove(this.lbQueries.SelectedItem);
        }

        private void btnApply_Click(object sender, RoutedEventArgs e)
        {
            this.netExSetting.ExcludeEntityTypes=new List<EntityType>();
            if(!this.ckGrants.IsChecked.Value)
                this.netExSetting.ExcludeEntityTypes.Add(EntityType.Grants);
            if (!this.ckOrgs.IsChecked.Value)
                this.netExSetting.ExcludeEntityTypes.Add(EntityType.Organizations);
            if (!this.ckPersons.IsChecked.Value)
                this.netExSetting.ExcludeEntityTypes.Add(EntityType.Persons);
            if (!this.ckPubs.IsChecked.Value)
                this.netExSetting.ExcludeEntityTypes.Add(EntityType.Publications);
            this.netExSetting.ExcludeQueries=new List<EntityQuery>();
            Regex querySpliter=new Regex(@"\.|=|<|>|<>|in|like",RegexOptions.IgnoreCase);
            Regex opRegex = new Regex(@"=|<|>|<>|in|like");
            foreach(object item in this.lbQueries.Items)
            {
                string[] parts = querySpliter.Split(item.ToString());
                List<string> partList=new List<string>();
                foreach(string part in parts)
                {
                    if(part.Trim().Length>0)
                        partList.Add(part.Trim());
                }
                if(partList.Count==3)
                {
                    EntityQuery query=new EntityQuery();
                    query.EntityType = (EntityType) Enum.Parse(typeof (EntityType), partList[0]);
                    query.FieldName = partList[1];
                    query.Against = partList[2];
                    Match opMatch = opRegex.Match(item.ToString());
                    if(opMatch.Success)
                    {
                        query.Op = SqlOpHelper.Parse(opMatch.Value);
                    }
                    if(item.ToString().IndexOf("<>")>0)
                        query.Op = SqlOp.NotEqual;
                    this.netExSetting.ExcludeQueries.Add(query);
                }
            }
            this.netExSetting.ExcludedEdges=new List<EdgeSelection>();
            if(!this.ckGO.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Grants,EntityType.Organizations));
            if (!this.ckGPs.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Grants, EntityType.Persons));
            if (!this.ckGPb.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Grants, EntityType.Publications));
            
            if (!this.ckOG.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Organizations, EntityType.Grants));
            if (!this.ckOPb.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Organizations, EntityType.Publications));
            if (!this.ckOPs.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Organizations, EntityType.Persons));
            
            if (!this.ckPsG.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Persons, EntityType.Grants));
            if (!this.ckPsO.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Persons, EntityType.Organizations));
            if (!this.ckPsPb.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Persons, EntityType.Publications));
            
            if (!this.ckPbG.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Grants, EntityType.Grants));
            if (!this.ckPbO.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Grants, EntityType.Organizations));
            if (!this.ckPbPs.IsChecked.Value)
                this.netExSetting.ExcludedEdges.Add(new EdgeSelection(EntityType.Grants, EntityType.Persons));

            this.netExSetting.Save();
            if (this.NetworkExclustionSettingUpdated != null)
                this.NetworkExclustionSettingUpdated(this.netExSetting);

            if (this.Parent is Window)
                ((Window)this.Parent).Close();
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            if (this.Parent is Window)
                ((Window)this.Parent).Close();
        }
    }
}
